package com.gem.day04;

import java.util.Arrays;

/**
 * 本类用来演示Java JVM内存结构
 * 
 * 1.寄存器 CPU
 * 2.本地方法区 操作系统
 * 
 * 3.方法区
 * 4.堆
 * 5.栈
 * 
 * @author easonsy
 * 2020年7月21日 上午11:21:30
 */
public class Jvm {
	/**
	 * 当启动main方法时,JVM加载当前类到方法区暂存
	 */
	public static void main(String[] args) {
		//基本类型保存在栈区
		int i = 3;
		System.out.println(i);

		//arr数组对象保存在堆空间中,并且该保存区域的内存地址保存在arr这个变量中,该变量保存在栈中
		//栈中的arr指向了堆空间中的真正对象
		int[] arr = { 1, 2, 3 };
		//把null赋值给arr,arr中保存了null,而堆中的数组对象没有任何引用所指向,变成了垃圾对象
		//垃圾对象最终会被JVM的垃圾回收机制(GC)自动回收
		arr = null;

		//java.lang.NullPointerException,空指针异常
		//System.out.println(arr.length);

		System.out.println("---------------------------");
		/*
		 * 结论:
		 * 1.一个对象能不能在同一个时刻被多个引用所指向呢?			可以
		 * 2.一个引用能不能在同一个时刻指向不同的对象呢?		  	不可以
		 */
		int[] arr1 = { 1, 2, 3 };
		//arr1和arr2中保存的内存地址是相同的,并且同时指向堆空间中的数组对象
		int[] arr2 = arr1;
		arr1[0] = -1;
		System.out.println(Arrays.toString(arr1));
		System.out.println(Arrays.toString(arr2));

		System.out.println("---------------------------");

		/*
		 * 参数传递问题:
		 * 1.形参:方法的参数列表定义的参数,没有具体数值
		 * 2.实参:调用方法时传入的具体数值
		 * 
		 * 基本类型: 值传递,把实参拷贝一份传给形参,方法中修改的是实参的副本,
		 * 					所以原实参数值不变
		 * 对象类型:引用传递,把对象的内存地址拷贝一份给形参,所以方法形参中
		 * 					保存的就是实参中的内存地址,而此内存地址就是指向堆空
		 * 					唯一的那个对象,所以方法中一旦通过引用修改了对象,则使用
		 * 					原引用访问时,对象会发生改变!
		 */
		int num = 1;
		int result = method1(num);
		System.out.println(num);//1
		System.out.println(result);//2

		System.out.println(">>>>>>>>>>>>>>>>");

		int[] intArr = { 1, 2, 3 };
		int[] result2 = method2(intArr);
		System.out.println(Arrays.toString(intArr));//2,3,4
		System.out.println(Arrays.toString(result2));//2,3,4
	}

	public static int method1(int num) {
		num += 1;
		return num;
	}

	public static int[] method2(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			arr[i] += 1;
		}
		return arr;
	}
}
